import cv2
import numpy as np
"""
实现图片的对其操作
"""
MAX_MATCHES = 4000
GOOD_MATCH_PERCENT = 0.3
def alignImages(im1, im2, itern=1):
    """
    对齐两张图像：将 im1 图像对齐到 im2 图像上。
    参数:
        im1: 待对齐图像
        im2: 参考图像
        itern: 对齐迭代次数（默认为 1）
    返回:
        对齐后的 im1 图像
    """
    # 将参考图像转换为灰度图
    im2Gray = cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY)
    # 初始化 ORB 特征检测器，设置最大特征点数
    orb = cv2.ORB_create(MAX_MATCHES)
    # 检测参考图像中的关键点和描述符
    keypoints2, descriptors2 = orb.detectAndCompute(im2Gray, None)
    # 创建 Hamming 距离的暴力匹配器（适用于 ORB）
    matcher = cv2.DescriptorMatcher_create(cv2.DESCRIPTOR_MATCHER_BRUTEFORCE_HAMMING)
    # 多次迭代图像配准（一般 itern=1 就够了）
    for k in range(itern):
        # 每次迭代都重新计算待对齐图像的灰度图和特征
        im1Gray = cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY)
        keypoints1, descriptors1 = orb.detectAndCompute(im1Gray, None)
        # 匹配特征描述符
        matches = matcher.match(descriptors1, descriptors2, None)
        matches = list(matches)
        # 根据距离对匹配项进行排序（距离越小匹配越好）
        matches.sort(key=lambda x: x.distance)
        # 只保留前 GOOD_MATCH_PERCENT 百分比的优质匹配
        numGoodMatches = int(len(matches) * GOOD_MATCH_PERCENT)
        matches = matches[:numGoodMatches]
        # 可视化匹配结果并保存为图像文件
        imMatches = cv2.drawMatches(im1, keypoints1, im2, keypoints2, matches, None)
        # cv2.imwrite("matches_{}.jpg".format(k), imMatches)
        # 提取优质匹配点的坐标
        points1 = np.zeros((len(matches), 2), dtype=np.float32)
        points2 = np.zeros((len(matches), 2), dtype=np.float32)
        for i, match in enumerate(matches):
            points1[i, :] = keypoints1[match.queryIdx].pt  # im1 中的点
            points2[i, :] = keypoints2[match.trainIdx].pt  # im2 中的点
        # 计算单应性矩阵（Homography），用于图像变换
        h, mask = cv2.findHomography(points1, points2, cv2.RANSAC)
        # 使用单应性矩阵将 im1 变换到 im2 的坐标系
        height, width, channels = im2.shape
        # im1 = cv2.warpPerspective(im1, h, (width, height))
        # 使用单应性矩阵将 im1 变换到 im2 的坐标系，并设置空白区域填充为白色
        im1 = cv2.warpPerspective(im1, h, (width, height), borderValue=(255, 255, 255))
    return im1